/* Copyright (C) 2017-2100 All right reserved
 * For free
 *
 * @file list.h
 * @brief  list 头文件
 * @author qigaohua, qigaohua168@163.com
 * @version 0.0.1
 * @date 2020-08-06
 */


#ifndef __LIST_H_
#define __LIST_H_


#ifdef _cplusplus
extern "C" {
#endif

#define RUN_DEBUG_MODE
#ifdef RUN_DEBUG_MODE
#ifndef BUG_ON
#define str(x)      #x
#define xstr(x)     str(x)
#define BUG_ON(expr) {      \
        if ((expr)) { \
            fprintf(stderr, "BUG ON at %s:%d(%s)\r\n", __FILE__,__LINE__, __func__);    \
            fprintf(stderr, "Error code : %s\r\n", xstr(expr));                         \
            exit(1);                    \
        }   \
    }
#endif
#else
#define BUG_ON(expr)
#endif


#define MALLOC malloc
#define FREE   free


typedef int (*list_node_cmp) (const void*, const void*);
typedef void(*list_node_free)(void*);


typedef struct _list_node {
    struct _list_node *next;
    struct _list_node *prev;
    void *val;
} list_node_t;


typedef struct _list {
    list_node_t *first;
    list_node_t *last;
#ifdef _USE_FREE_NODE  // TODO
    list_node_t *free;
#endif
    int cnt;

    list_node_free node_free;
    list_node_cmp node_cmp;
} list_t;


#if 0
// TODO: 迭代器
typedef enum {
    LIST_NEXT = 0,
    LIST_PREV
} list_direction_t;

typedef struct _list_iterator {
    list_node_t *n;
    list_direction_t dir;
} list_iterator_t;
#endif



void list_zero(list_t *l);
list_t *list_new();
void list_delete(list_t *l);
list_node_t* list_node_new(void *val);
list_node_t* list_insert_rignt(list_t *l, list_node_t *pos, void *val);
list_node_t* list_insert_left(list_t *l, list_node_t *pos, void *val);
list_node_t* list_rpush(list_t *l, void *val);
list_node_t* list_lpush(list_t *l, void *val);
list_node_t* list_iterator_next(list_t *l, list_node_t **n);
list_node_t* list_iterator_prev(list_t *l, list_node_t **p);
list_node_t* list_match_find(list_t *l, void *val, int(*item_cmp)(const void *, const void *));
list_node_t* list_at(list_t *l, int index);
list_node_t* list_find(list_t *l, void *val);
list_node_t* list_lpop(list_t *l);
list_node_t* list_rpop(list_t *l);
void list_unlink(list_t *l, list_node_t *node);
int  list_remove(list_t *l, void *val);
void list_set_free_func(list_t *l, list_node_free free);
void list_set_cmp_func(list_t *l, list_node_cmp cmp);


#ifdef _cplusplus
}
#endif


#endif
